﻿using System;
using System.Collections;
using System.Reflection;
using System.Runtime;
using System.Runtime.InteropServices;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Serialization;

using PickGold.Util.Proxies;

namespace PickGold.Util.Remoting
{
	/// <summary>
	/// 
	/// </summary>
	//[DataContract]
	//[Serializable]
	[ComVisible(true)]
	[ClassInterface(ClassInterfaceType.AutoDispatch)]
	sealed class MethodInvokerCallMessage : IMethodCallMessage, IMethodMessage, IMessage
	{
		/// <summary>
		/// 真正向远程传输并序列化的成员。
		/// </summary>
		public CMethodCallMessage _Storage;

		public MethodInvokerCallMessage(CMethodCallMessage mcm)
		{
			this._Storage = mcm;
		}

		public MethodInvokerCallMessage(IMethodCallMessage mcm)
		{
			this._Storage = new CMethodCallMessage();
			if (mcm.Properties != null && mcm.Properties.Count > 0)
			{
				this._Storage.Properties = new Hashtable();
				foreach (var key in mcm.Properties.Keys)
					this._Storage.Properties[key] = mcm.Properties[key];
			}
			try
			{
				this._Storage.InArgs = mcm.InArgs;
				if (this._Storage.InArgs != null && this._Storage.InArgs.Length == 0)
				{
					this._Storage.InArgs = null;
				}
				else
				{
					this._Storage.InArgNames = new string[this.InArgCount];
					for (var i = 0; i < this.InArgCount; i++)
						this._Storage.InArgNames[i] = mcm.GetInArgName(i);
				}
			}
			catch (Exception x)
			{
				Common.LastError = x;
			}
			try
			{
				this._Storage.Args = mcm.Args;
				if (this._Storage.Args != null && this._Storage.Args.Length == 0)
				{
					this._Storage.Args = null;
				}
				else
				{
					this.Storage.ArgNames = new string[this.ArgCount];
					for (var i = 0; i < this.ArgCount; i++)
						this.Storage.ArgNames[i] = mcm.GetArgName(i);
				}
			}
			catch (Exception x)
			{
				Common.LastError = x;
			}
			this._Storage.LogicalCallContext = mcm.LogicalCallContext;
			this._Storage.MethodBase = mcm.MethodBase;
			this._Storage.MethodName = mcm.MethodName;
			this._Storage.MethodSignature = mcm.MethodSignature;
			this._Storage.TypeName = mcm.TypeName;
			this._Storage.Uri = mcm.Uri;
		}

		/// <summary>
		/// 真正向远程传输并序列化的成员。
		/// </summary>
		public CMethodCallMessage Storage
		{
			get
			{
				return this._Storage;
			}
		}

		#region IMethodCallMessage 成员

		public object GetInArg(int argNum)
		{
			return this.Storage.InArgs[argNum];
		}

		public string GetInArgName(int index)
		{
			return this.Storage.InArgNames[index];
		}

		public int InArgCount
		{
			get
			{
				if (this.Storage.InArgs == null)
					return 0;

				return this.Storage.InArgs.Length;
			}
		}

		public object[] InArgs
		{
			set
			{
				this.Storage.InArgs = value;
			}
			get
			{
				return this.Storage.InArgs;
			}
		}

		#endregion

		#region IMethodMessage 成员

		public int ArgCount
		{
			get
			{
				if (this.Storage.Args == null)
					return 0;

				return this.Storage.Args.Length;
			}
		}

		public object[] Args
		{
			set
			{
				this.Storage.Args = value;
			}
			get
			{
				return this.Storage.Args;
			}
		}

		public object GetArg(int argNum)
		{
			return this.Storage.Args[argNum];
		}

		public string GetArgName(int index)
		{
			return this.Storage.ArgNames[index];
		}

		public bool HasVarArgs
		{
			get
			{
				if (this.Storage.Args == null || this.Storage.Args.Length == 0)
					return false;

				return true;
			}
		}

		public LogicalCallContext LogicalCallContext
		{
			set
			{
				this.Storage.LogicalCallContext = value;
			}
			get
			{
				return this.Storage.LogicalCallContext;
			}
		}

		public MethodBase MethodBase
		{
			set
			{
				this.Storage.MethodBase = value;
			}
			get
			{
				return this.Storage.MethodBase;
			}
		}

		public string MethodName
		{
			set
			{
				this.Storage.MethodName = value;
			}
			get
			{
				return this.Storage.MethodName;
			}
		}

		public object MethodSignature
		{
			set
			{
				this.Storage.MethodSignature = value;
			}
			get
			{
				return this.Storage.MethodSignature;
			}
		}

		public string TypeName
		{
			set
			{
				this.Storage.TypeName = value;
			}
			get
			{
				return this.Storage.TypeName;
			}
		}

		public string Uri
		{
			set
			{
				this.Storage.Uri = value;
			}
			get
			{
				return this.Storage.Uri;
			}
		}

		#endregion

		#region IMessage 成员

		public IDictionary Properties
		{
			set
			{
				this.Storage.Properties = value;
			}
			get
			{
				return this.Storage.Properties;
			}
		}

		#endregion
	}

	[DataContract]
	[Serializable]
	[ComVisible(true)]
	sealed class CMethodCallMessage : CMessage
	{
		public override void ProcessPropertiesProxy(bool onSerializing)
		{
			base.ProcessPropertiesProxy(onSerializing);
			if (this.InArgs == null || this.InArgs.Length == 0)
				return;

			if (onSerializing)//如果正在序列化。
				this.InProxyArgs = CMessage.ProcessPropertiesProxy(this.InArgs, null);

			if (this.InProxyArgs == null || this.InProxyArgs.Length == 0)//反序列化，如果不存在真实代理
				return;

			CMessage.ProcessPropertiesProxy(this.InArgs, this.InProxyArgs);
		}

		public object[] InArgs;

		public string[] InArgNames;

		private object[] InProxyArgs;
	}
}
